package com.tiancheng.onecode.trade.utils;

import cn.hutool.core.map.MapUtil;
import com.dtflys.forest.Forest;
import com.dtflys.forest.config.ForestConfiguration;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestRequestType;
import com.tiancheng.onecode.exception.ErrorCodeException;
import com.tiancheng.onecode.utils.JsonUtil;
import org.apache.http.Header;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: kellen
 * @Description:
 * @Date: create in 2024/11/21 11:16
 */
public class ForestHttpUtil {
    private static ForestConfiguration configuration;
    private static ForestHttpUtil httpUtils;

    private ForestHttpUtil() {
    }

    public static synchronized ForestHttpUtil getInstance() {
        if (httpUtils == null) {
            httpUtils = new ForestHttpUtil();
            initialize();
        }
        return httpUtils;
    }

    private static void initialize() {
        configuration = Forest.config();
        // 连接池最大连接数
        configuration.setMaxConnections(1000);
        // 连接超时时间，单位为毫秒
        configuration.setConnectTimeout(2000);
        // 数据读取超时时间，单位为毫秒
        configuration.setReadTimeout(10000);
    }


    /**
     *  http post signature方式
     * @param url
     * @param bodyParam 参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String doPostJson(String url, Object bodyParam,Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        request.contentTypeJson();
        setHeader(request, headers);
        setParams(request, null, bodyParam, false);
        AtomicReference<String> result =new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new RuntimeException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }

    /**
     *  http post signature方式
     * @param url
     * @param bodyParam 参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String doPost(String url, Object bodyParam,Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        setHeader(request, headers);
        setParams(request, null, bodyParam, true);
        AtomicReference<String> result =new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new ErrorCodeException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }

    /**
     *  http get signature方式
     * @param url
     * @param params 参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String get(String url, Object params,Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.GET);
        request.addQuery(params);
        if(null!=headers){
            for (Header header : headers) {
                request.addHeader(header.getName(),header.getValue());
            }
        }
        request.addHeader("Content-type","application/x-www-form-urlencoded");
        AtomicReference<String> result =new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new ErrorCodeException("请求异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }


    /**
     *  http post signature方式
     * @param url
     * @param file 参数
     * @param headers 请求头
     * @return
     * @throws Throwable
     */
    public String multipartForm(String url, MultipartFile file,Map<String,Object> params,Header... headers) {
        ForestRequest<?> request = configuration.request();
        request.url(url);
        request.setType(ForestRequestType.POST);
        request.contentTypeMultipartFormData();
        request.setReadTimeout(10*1000);
        request.connectTimeout(5*1000);
        if(null!=params && params.size()>0){
            request.addQuery(params);
        }
        setHeader(request, headers);
        try {
            request.addFile("file",file.getInputStream(),file.getOriginalFilename());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        AtomicReference<String> result =new AtomicReference<>();
        request.onSuccess((data, forestRequest, forestResponse) -> {
            result.set(JsonUtil.toJsonString(data));
        });
        request.onError((ex, forestRequest, forestResponse) -> {
            throw new ErrorCodeException("上传文件异常:" + ex.getMessage());
        });
        request.execute();
        return result.get();
    }

    private void setParams(ForestRequest<?> request, Map<String, Object> urlParams, Object bodyParam, boolean useFormData) {
        if (MapUtil.isNotEmpty(urlParams)) {
            request.addQuery(urlParams);
        }
        if (Objects.nonNull(bodyParam)) {
            if (useFormData) {
                request.addQuery(bodyParam);
            } else {
                request.addBody(bodyParam);
            }
        }
    }

    /**
     * 设置请求头
     *
     * @param request
     * @param headers
     */
    private void setHeader(ForestRequest<?> request, Header... headers) {
        if (null != headers) {
            for (Header header : headers) {
                request.addHeader(header.getName(), header.getValue());
            }
        }
    }
}
